package cn.tedu.ivos.application.service.impl;

import cn.tedu.ivos.application.mapper.ApplicationMapper;
import cn.tedu.ivos.application.pojo.dto.ApplicationQueryDTO;
import cn.tedu.ivos.application.pojo.dto.ApplicationSaveParamDTO;
import cn.tedu.ivos.application.pojo.entity.Application;
import cn.tedu.ivos.application.pojo.vo.ApplicationVO;
import cn.tedu.ivos.application.service.ApplicationService;
import cn.tedu.ivos.audit.mapper.AuditMapper;
import cn.tedu.ivos.audit.pojo.vo.AuditVO;
import cn.tedu.ivos.audit.service.AuditService;
import cn.tedu.ivos.base.enums.ApplicationStatusEnum;
import cn.tedu.ivos.user.mapper.UserMapper;
import cn.tedu.ivos.user.pojo.vo.UserVO;
import cn.tedu.ivos.vehicle.mapper.VehicleMapper;
import cn.tedu.ivos.vehicle.pojo.entity.Vehicle;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringJoiner;

@Transactional
@Slf4j
@Service
public class ApplicationServiceImpl implements ApplicationService {

    @Autowired
    ApplicationMapper applicationMapper;

    @Autowired
    AuditService auditService;

    @Autowired
    AuditMapper auditMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    VehicleMapper vehicleMapper;

    /**
     * 保存一个application申请对象
     * @param saveParams
     * @return
     */
    public void saveApplication(ApplicationSaveParamDTO saveParams) {
        Application application=new Application();
        //将前端传过来的数据赋值给application对象
        BeanUtils.copyProperties(saveParams,application);
        //新增的申请单,初始状态为"已发起"
        //由于业务原因,没有修改,可以实现撤销,然后重新发申请
        application.setStatus(ApplicationStatusEnum.PENDING.getCode());
        application.setCreateTime(new Date());
        /*遇到的问题:新增申请对应的审批数据,但审批数据里没有申请单的id,怎么办?*/
        //因为我们要给即将生成的审批单设置申请单id,但申请单的id无法通过任何条件select获取
        //所以需要给此insert方法对应的SQL上进行配置:useGeneratedKeys="true" keyProperty="id"
        //这两句代码的作用是让jdbc为当前的application对象自动生成自增主键
        //并将自增主键的值赋值给当前application对象的id字段
        applicationMapper.insert(application);
        //还需要调用审批业务层,为当前申请单同步新增对应的审批数据
        auditService.insertAudit(application);
    }

    /**
     * 根据条件appQueryDTO查询: 申请单列表
     * 注意：
     * 1.查询所有申请数据，
     * 2.同时需要查询申请单对应的审批人信息赋值给申请单对象(需要用auditMapper查询)
     * 3.查询审批人数据的同时还要查询审批人的id和审批人的username(还需要用到UserMapper根据Id查询User数据)
     * @param appQueryDTO
     * @return
     */
    public List<ApplicationVO> selectApplications(ApplicationQueryDTO appQueryDTO) {
        log.debug("ApplicationServiceImpl-selectApplications{}",appQueryDTO);
        //根据查询条件,查询符合的申请单数据
        List<ApplicationVO> appList=applicationMapper.selectApplications(appQueryDTO);
        //遍历申请单集合,依次查出每个申请单对应的审批人数据
        for(int i = 0; i<appList.size(); i++){
            ApplicationVO appVO = appList.get(i);
            //申请单列表中需要审批人的相关信息,我们可以自定义方法给applicationVO设置相关的审批人数据
            //给审批对象设置： 审批人的信息(审批人id和审批人姓名)
            assignAuditUserList(appVO);
        }
        return appList;
    }

    /**
     *  根据id取消申请单:
     *  1.用applicationMapper更新申请单状态 和修改时间
     *  2.同时还要用auditMapper删除所有的对应的审批数据
     * @param id
     */
    public void cancelApp(Long id) {
        log.debug("ApplicationServiceImpl--cancelApp{id}", id);
        Application application=new Application();
        application.setId(id);
        //撤销需要将申请单状态改为"撤销"
        application.setStatus(ApplicationStatusEnum.CANCEL.getCode());
        application.setUpdateTime(new Date());
        applicationMapper.update(application);
        //还需要删除此申请单对应的所有审批单数据
        auditMapper.deleteByApplicationId(id);
    }




    @Override
    public void distribute(Long applicationId, Long vehicleId) {
        log.debug("分配车辆业务参数:申请单编号:{},车辆编号:{}",applicationId,vehicleId);
        Application application = new Application();
        application.setId(applicationId);
        application.setVehicleId(vehicleId);
        application.setStatus(ApplicationStatusEnum.ALLOCATION.getCode());
        application.setUpdateTime(new Date());
        applicationMapper.update(application);

        Vehicle vehicle = new Vehicle();
        vehicle.setId(vehicleId);
        vehicle.setStatus("2");//占用
        vehicle.setUpdateTime(new Date());
        vehicleMapper.updateVehicle(vehicle);
    }


    @Override
    public void back(Long applicationId, Long vehicleId) {
        log.debug("还车业务参数:申请单编号:{},车辆编号:{}",applicationId,vehicleId);
        Application application = new Application();
        application.setId(applicationId);
        application.setVehicleId(null);
        application.setStatus(ApplicationStatusEnum.END.getCode());
        application.setUpdateTime(new Date());
        applicationMapper.back(application);

        Vehicle vehicle = new Vehicle();
        vehicle.setId(vehicleId);
        vehicle.setStatus("1");//空闲
        vehicle.setUpdateTime(new Date());
        vehicleMapper.updateVehicle(vehicle);
    }


    /* 为申请单VO补全审批人信息,此方法并不会产生额外的申请单VO!
     * List<Long> auditUserIdList; //[106,103]
     * String auditUsernameList; //"moly,tom"
     */
    public void assignAuditUserList(ApplicationVO applicationVO) {//assign：指定，指派
        List<Long> auditUserIdList = new ArrayList<>();//准备空集合用来存放审批人id
        List<String> auditUsernameList = new ArrayList<>();//准备空集合用来存放审批人姓名
        //获取此申请单对应的多条审批单数据
        List<AuditVO> auditVOList =auditService.selectAuditByApplicationId(applicationVO.getId());
        //遍历得到每条审批单数据
        for(int i = 0; i < auditVOList.size(); i++){
            //拿到当前遍历到的审批单数据
            AuditVO auditVO = auditVOList.get(i);
            //从审批人数据中获取审批人id
            Long id = auditVO.getAuditUserId();
            auditUserIdList.add(id);//添加到空集合中
            UserVO userVO = userMapper.selectUserById(id);//根据审批人id查询审批人VO
            auditUsernameList.add(userVO.getUsername());//将审批人姓名存入空集合中
        }
        //准备拼接工具,拼接的连接符号是逗号
        StringJoiner stringJoiner = new StringJoiner(",");
        //依次将姓名集合中的审批人姓名添加到拼接工具中
        for(String username : auditUsernameList){
            stringJoiner.add(username);
        }
        //为传入的申请单VO补全审批人id集合与审批人姓名字符串数据
        applicationVO.setAuditUserIdList(auditUserIdList);//[106,103]
        applicationVO.setAuditUsernameList(stringJoiner.toString());//moly,tom
    }


}
